home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / src / pop / lock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-28  |  5.8 KB  |  355 lines

  1. /* lock.c - universal locking routines */
  2.  
  3. #ifndef    MMDFONLY
  4. #include "../h/strings.h"
  5. #else /* MMDFONLY */
  6. #include "strings.h"
  7. #include "mmdfonly.h"
  8. #endif /* MMDFONLY */
  9. #include <stdio.h>
  10. #include "mts.h"
  11. #include "util.h"
  12. #include <sys/stat.h>
  13.  
  14.  
  15. #define    NOTOK    (-1)
  16. #define    OK    0
  17.  
  18. #define    NULLCP    ((char *) 0)
  19.  
  20.  
  21. extern int  errno;
  22.  
  23. /*   */
  24.  
  25. int    lkopen (file, access)
  26. register char   *file;
  27. register int     access;
  28. {
  29.     mts_init ("mts");
  30.     switch (lockstyle) {
  31.     case LOK_UNIX:
  32. #ifdef    BSD42
  33.         return f_lkopen (file, access);
  34. #endif /* BSD42 */
  35.  
  36.     default:
  37.         return b_lkopen (file, access);
  38.     }
  39. }
  40.  
  41. /*   */
  42.  
  43. static int  b_lkopen (file, access)
  44. register char   *file;
  45. register int     access;
  46. {
  47.     register    int    i,
  48.             j;
  49.     time_t    curtime;
  50.     char    curlock[BUFSIZ],
  51.         tmplock[BUFSIZ];
  52.     struct    stat    st;
  53.  
  54.     if (stat (file, &st) == NOTOK)
  55.     return NOTOK;
  56.     lockname (curlock, tmplock, file, (int) st.st_dev, (int) st.st_ino);
  57.  
  58.     for (i = 0;;)
  59.     switch (lockit (tmplock, curlock)) {
  60.         case OK: 
  61.         if ((i = open (file, access)) == NOTOK) {
  62.             j = errno;
  63.             (void) unlink (curlock);
  64.             errno = j;
  65.         }
  66.         timerON (curlock, i);
  67.         return i;
  68.  
  69.         case NOTOK: 
  70.         if (stat (curlock, &st) == NOTOK) {
  71.             if (i++ > 5)
  72.             return NOTOK;
  73.             sleep (5);
  74.             break;
  75.         }
  76.  
  77.         i = 0;
  78.         (void) time (&curtime);
  79.         if (curtime < st.st_ctime + 60L)
  80.             sleep (5);
  81.         else
  82.             (void) unlink (curlock);
  83.         break;
  84.     }
  85. }
  86.  
  87.  
  88. static int  lockit (tmp, file)
  89. register char   *tmp,
  90.             *file;
  91. {
  92.     register int    fd;
  93.  
  94.     if ((fd = creat (tmp, 0400)) == NOTOK)
  95.     return NOTOK;
  96.     (void) close (fd);
  97.  
  98.     fd = link (tmp, file);
  99.     (void) unlink (tmp);
  100.  
  101.     return (fd != NOTOK ? OK : NOTOK);
  102. }
  103.  
  104. /*   */
  105.  
  106. static  lockname (curlock, tmplock, file, dev, ino)
  107. register char   *curlock,
  108.             *tmplock,
  109.             *file;
  110. register int     dev,
  111.          ino;
  112. {
  113.     register char  *bp,
  114.                    *cp;
  115.  
  116.     bp = curlock;
  117.     if ((cp = rindex (file, '/')) == NULL || *++cp == NULL)
  118.     cp = file;
  119.     if (lockldir == NULL || *lockldir == NULL) {
  120.     if (cp != file) {
  121.         (void) sprintf (bp, "%.*s", cp - file, file);
  122.         bp += strlen (bp);
  123.     }
  124.     }
  125.     else {
  126.     (void) sprintf (bp, "%s/", lockldir);
  127.     bp += strlen (bp);
  128.     }
  129.  
  130.     switch (lockstyle) {
  131.     case LOK_BELL: 
  132.     default: 
  133.         (void) sprintf (bp, "%s.lock", cp);
  134.         break;
  135.  
  136.     case LOK_MMDF: 
  137.         (void) sprintf (bp, "LCK%05d.%05d", dev, ino);
  138.         break;
  139.     }
  140.  
  141.     if (tmplock) {
  142.     if ((cp = rindex (curlock, '/')) == NULL || *++cp == NULL)
  143.         (void) strcpy (tmplock, ",LCK.XXXXXX");
  144.     else
  145.         (void) sprintf (tmplock, "%.*s,LCK.XXXXXX",
  146.         cp - curlock, curlock);
  147.     (void) unlink (mktemp (tmplock));
  148.     }
  149. }
  150.  
  151. /*   */
  152.  
  153. #ifdef    BSD42
  154.  
  155. #include <sys/file.h>
  156. #include <fcntl.h>
  157.  
  158. static int  f_lkopen (file, access)
  159. register char   *file;
  160. register int     access;
  161. {
  162.     register int    fd,
  163.                     i,
  164.             j;
  165.  
  166.     for (i = 0; i < 5; i++) {
  167.     if ((fd = open (file, access | O_NDELAY)) == NOTOK)
  168.         return NOTOK;
  169.     if (flock (fd, LOCK_EX | LOCK_NB) != NOTOK)
  170.         return fd;
  171.     j = errno;
  172.     (void) close (fd);
  173.  
  174.     sleep (5);
  175.     }
  176.  
  177.     (void) close (fd);
  178.     errno = j;
  179.     return NOTOK;
  180. }
  181. #endif /* BSD42 */
  182.  
  183. /*   */
  184.  
  185. /* ARGSUSED */
  186.  
  187. int     lkclose (fd, file)
  188. register int     fd;
  189. register char   *file;
  190. {
  191.     char    curlock[BUFSIZ];
  192.     struct stat st;
  193.  
  194.     if (fd == NOTOK)
  195.     return OK;
  196.     switch (lockstyle) {
  197.     case LOK_UNIX: 
  198. #ifdef    BSD42
  199.         break;
  200. #endif /* BSD42 */
  201.  
  202.     default: 
  203.         if (fstat (fd, &st) != NOTOK) {
  204.         lockname (curlock, NULLCP, file, (int) st.st_dev, (int) st.st_ino);
  205.         (void) unlink (curlock);
  206.         timerOFF (fd);
  207.         }
  208.     }
  209.  
  210.     return (close (fd));
  211. }
  212.  
  213.  
  214. /*   */
  215.  
  216. FILE    *lkfopen (file, mode)
  217. register char   *file,
  218.              *mode;
  219. {
  220.     register int    fd;
  221.     register FILE  *fp;
  222.  
  223.     if ((fd = lkopen (file, strcmp (mode, "r") ? 2 : 0)) == NOTOK)
  224.     return NULL;
  225.  
  226.     if ((fp = fdopen (fd, mode)) == NULL) {
  227.     (void) close (fd);
  228.     return NULL;
  229.     }
  230.  
  231.     return fp;
  232. }
  233.  
  234.  
  235. /* ARGSUSED */
  236.  
  237. int    lkfclose (fp, file)
  238. register FILE    *fp;
  239. register char    *file;
  240. {
  241.     char    curlock[BUFSIZ];
  242.     struct stat st;
  243.  
  244.     if (fp == NULL)
  245.     return OK;
  246.  
  247.     switch (lockstyle) {
  248.     case LOK_UNIX: 
  249. #ifdef    BSD42
  250.         break;
  251. #endif /* BSD42 */
  252.  
  253.     default: 
  254.         if (fstat (fileno (fp), &st) != NOTOK) {
  255.         lockname (curlock, NULLCP, file, (int) st.st_dev, (int) st.st_ino);
  256.         (void) unlink (curlock);
  257.         }
  258.     }
  259.  
  260.     return (fclose (fp));
  261. }
  262.  
  263. /*   */
  264.  
  265. #include <signal.h>
  266.  
  267. #define    NSECS    ((unsigned) 20)
  268.  
  269.  
  270. struct lock {
  271.     int         l_fd;
  272.     char    *l_lock;
  273.     struct lock *l_next;
  274. };
  275. #define    NULLP    ((struct lock *) 0)
  276.  
  277. static struct lock *l_top = NULLP;
  278.  
  279.  
  280. /* ARGSUSED */
  281.  
  282. static alrmser (sig)
  283. int    sig;
  284. {
  285.     register int    j;
  286.     register char  *cp;
  287.     register struct lock   *lp;
  288.  
  289. #ifndef    BSD42
  290.     (void) signal (SIGALRM, alrmser);
  291. #endif /* BSD42 */
  292.  
  293.     for (lp = l_top; lp; lp = lp -> l_next)
  294.     if (*(cp = lp -> l_lock) && (j = creat (cp, 0400)) != NOTOK)
  295.         (void) close (j);
  296.  
  297.     (void) alarm (NSECS);
  298. }
  299.  
  300. /*   */
  301.  
  302. static timerON (lock, fd)
  303. char   *lock;
  304. int    fd;
  305. {
  306.     register struct lock   *lp;
  307.  
  308.     if ((lp = (struct lock *) malloc ((unsigned) (sizeof *lp))) == NULLP)
  309.     return;            /* XXX */
  310.  
  311.     lp -> l_fd = fd;
  312.     if ((lp -> l_lock = malloc ((unsigned) (strlen (lock) + 1))) == NULLCP) {
  313.     free ((char *) lp);
  314.     return;            /* XXX */
  315.     }
  316.     (void) strcpy (lp -> l_lock, lock);
  317.     lp -> l_next = NULLP;
  318.  
  319.     if (l_top)
  320.     lp -> l_next = l_top -> l_next;
  321.     else {
  322.     (void) signal (SIGALRM, alrmser);/* perhaps SIGT{STP,TIN,TOU} */
  323.     (void) alarm (NSECS);
  324.     }
  325.     l_top = lp;
  326. }
  327.  
  328.  
  329. static timerOFF (fd)
  330. int    fd;
  331. {
  332.     register struct lock   *pp,
  333.                            *lp;
  334.  
  335.     (void) alarm (0);
  336.  
  337.     if (l_top) {
  338.     for (pp = lp = l_top; lp; pp = lp, lp = lp -> l_next)
  339.         if (lp -> l_fd == fd)
  340.         break;
  341.     if (lp) {
  342.         if (lp == l_top)
  343.         l_top = lp -> l_next;
  344.         else
  345.         pp -> l_next = lp -> l_next;
  346.  
  347.         free (lp -> l_lock);
  348.         free ((char *) lp);
  349.     }
  350.     }
  351.  
  352.     if (l_top)
  353.     (void) alarm (NSECS);
  354. }
  355.